package org.fastsyncer.parser.ldap;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.naming.NamingEnumeration;
import javax.naming.directory.Attributes;
import javax.naming.ldap.LdapName;

import org.fastsyncer.common.constant.ConnectorConstant;
import org.fastsyncer.common.entity.LdapConfig;
import org.fastsyncer.common.entity.Mapping;
import org.fastsyncer.common.entity.MappingTask;
import org.fastsyncer.connector.framework.ConnectorFactory;
import org.fastsyncer.connector.ldap.LdapConnector;
import org.springframework.ldap.NamingException;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.support.LdapNameBuilder;

public class LdapParser {

	// 实现单例模式的方法，通过方法来实现实例化
	// 声明一个私有的静态属性，使只被实例化一次
	private static final LdapParser instance = new LdapParser();

	// 声明一个私有的构造方法，使别人不能随便new对象
	// 它只被调用一次，实例存在之后就不再调用了
	private LdapParser() {
	}

	// 声明一个公共的静态方法，外界通过调用这个方法来得到唯一的实例
	public static LdapParser getInstance() {
		return instance;
	}

	/**
	 * 解析数据源ldap类型
	 * 
	 * @param mappingTask
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List<Map<String, Object>> parseSource(MappingTask mappingTask) throws Exception {
		Mapping sourceMapping = mappingTask.getSourceMapping();
		LdapConnector conn = (LdapConnector) ConnectorFactory.getInstance(sourceMapping.getConnector());
		// 数据源实例
		LdapConfig sourceConfig = (LdapConfig) sourceMapping.getConfig();
		LdapTemplate ldapTemplate = conn.getLdapTemplate(sourceConfig);

		// 转换器
		AttributesMapper mapper = new AttributesMapper() {
			public Object mapFromAttributes(Attributes attrs) throws NamingException, javax.naming.NamingException {
				Map<String, Object> r = new HashMap<String, Object>();
				NamingEnumeration<String> iDs = attrs.getIDs();
				while (iDs.hasMoreElements()) {
					String key = (String) iDs.nextElement();
					Object value = attrs.get(key).get();
					r.put(key, value);
				}
				return r;
			}
		};

		// 期望返回的数据格式 [{ID=123, NAME=张三11}, {ID=321, NAME=李四},...]
		// [{ou=scdl, objectClass=top, description=四川电力}, {loginShell=sss,
		// uid=ssvvcvcvcvcvc,
		// homeDirectory=ou=scdl_part1,ou=scdl,dc=aostar,dc=com,
		// uidNumber=10271, displayName=xxx, givenName=vbvbvvcvc,
		// objectClass=organizationalPerson, sn=sss, gidNumber=65534, cn=sss}]
		String filter = sourceMapping.getExcuteCommond().get(ConnectorConstant.OPERTION_QUERY);
		List<Map<String, Object>> search = ldapTemplate.search("", filter, mapper);
		return search;
	}

	/**
	 * 同步数据源ldap类型
	 * 
	 * @param mappingTask
	 * @param rows
	 * @return
	 * @throws Exception
	 */
	public Integer[] syncTarget(MappingTask mappingTask, List<Map<String, Object>> rows) throws Exception {

		Mapping sourceMapping = mappingTask.getSourceMapping();
		Mapping targetMapping = mappingTask.getTargetMapping();

		LdapConnector conn = (LdapConnector) ConnectorFactory.getInstance(sourceMapping.getConnector());
		LdapConfig config = (LdapConfig) sourceMapping.getConfig();
		LdapTemplate ldapTemplate = conn.getLdapTemplate(config);
		
		insert(ldapTemplate);
		return new Integer[] { 0, 0 };
	}
	
	public void insert(LdapTemplate ldapTemplate) {

		// 2.0版本推荐:DirContextAdapter是使用LDAP属性非常有用的工具，特别是添加或修改数据时。
		// 设置域 cn=yangp,ou=scdl,dc=aostar,dc=com
		LdapName build = LdapNameBuilder.newInstance().add("cn", "yangp").build();
		// new DirContextAdapter("cn=yangp");
		DirContextAdapter ctx = new DirContextAdapter(build);
		// 基本信息
		ctx.setAttributeValues("objectclass",
				new String[] { "person", "inetorgperson", "organizationalperson", "top" });
		// 属性
		ctx.addAttributeValue("description", "Grumpy");
		ctx.addAttributeValue("sn", "Hartnell");
		ctx.addAttributeValue("telephonenumber", "18299995202");
		ldapTemplate.bind(ctx);
		System.out.println("新增用户success!");
	}

}
